package com.ninong.ker.admin.conf;

import com.ninong.ker.common.auth.SecurityAdmin;
import com.ninong.ker.common.tools.CmdAdminTools;
import com.ninong.ker.common.user.OnlineUser;
import net.sf.jsqlparser.expression.StringValue;
import org.apache.commons.lang3.StringUtils;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;

import net.sf.jsqlparser.expression.Expression;
import org.springframework.data.redis.core.RedisTemplate;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * @author jmz
 */
@Configuration
public class MybatisPlusConfig {

    @Autowired
    private SecurityAdmin securityAdmin;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 新多租户插件配置,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存万一出现问题
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() {
            @Override
            public Expression getTenantId() {
                HttpServletRequest request = CmdAdminTools.getHttpServletRequest();
                String token = securityAdmin.getToken(request);
                if (StringUtils.isNotEmpty(token)) {
                    if (securityAdmin.validateToken(token)) {
                        OnlineUser user = securityAdmin.currentUser(token);
                        return new StringValue(user.getTenantId());
                    }
                }
                // 返回""代表什么都查不出来
                return new StringValue("");
            }

            // 这是 default 方法,默认返回 false 表示所有表都需要拼多租户条件
            @Override
            public boolean ignoreTable(String tableName) {
                HttpServletRequest request = CmdAdminTools.getHttpServletRequest();
                String requestRri = request.getRequestURI();
                List<String> allowPaths = redisTemplate.opsForList().range("allowPaths", 0, -1);
                // 跳过不需要验证的路径
                if (isAllowPath(requestRri, allowPaths)) {
                    return true;
                }
                String token = securityAdmin.getToken(request);
                if (StringUtils.isNotEmpty(token)) {
                    if (securityAdmin.validateToken(token)) {
                        OnlineUser user = securityAdmin.currentUser(token);
                        // 当租户id为空时，说明是超级管理员，无需过滤租户，可查看全部信息
                        if (StringUtils.isEmpty(user.getTenantId())) {
                            return true;
                        }
                    }
                }
                return "fw_tenant".equalsIgnoreCase(tableName) || "fw_menu".equalsIgnoreCase(tableName)|| "fw_user".equalsIgnoreCase(tableName);
            }
        }));
        return interceptor;
    }

    private boolean isAllowPath(String path, List<String> allowPaths) {
        // 遍历白名单
        for (String allowPath : allowPaths) {
            // 判断是否允许
            if (path.startsWith(allowPath.toString())) {
                return true;
            }
        }
        return false;
    }
}
